<!DOCTYPE HTML>
<html lang="zh" style="font-size:100px">

<head>
    <meta charset="utf-8" />
    <title>2018年上半年飞过的地方 - Hello全视界</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
    <script src="../lib/three.js"></script>
    <script src="../lib/vue.js"></script>
    <script type="text/javascript"
        src="https://api.map.baidu.com/api?v=2.0&ak=4woYXvjYCbrpX0jVGBO2Dy5SxLptnrBa&s=1"></script>

    <script src="../control_stick/util.js"></script>
    <script src="../control_stick/stick.js"></script>
    <script src="../js/bmap_handler.js"></script>
    <script src="../js/poi_handler.js"></script>
    <script src="../js/public.js"></script>


    <style>
        html,
        body,
        #app {
            padding: 0;
            margin: 0;
            overflow: hidden;
            width: 100vw;
            height: 100vh;
            min-height: 100vh;
        }

        body {
            font-family: sans-serif;
            line-height: 1em;
            font-size: 0.16rem;
        }

        button {
            font-size: 0.16rem;
            font-family: sans-serif;
        }

        div {
            box-sizing: border-box;
        }

        ul,
        li {
            list-style: none;
            margin: 0;
            padding: 0
        }

        h1,
        h2,
        h3,
        h4,
        h5,
        h6 {
            margin: 0;
            line-height: 1em
        }

        p {
            margin: 0;
        }

        [v-cloak] {
            display: none
        }

        a,
        a:link,
        a:visited,
        a:hover,
        a:active {
            text-decoration: none;
            color: #000
        }

        button,
        .buttonLike {
            cursor: pointer;
            user-select: none;
        }

        #app {
            position: relative;
        }

        .logo {
            position: absolute;
            margin: 0.2rem 0 0 0.4rem;
            z-index: 999;

        }

        .logo>img {
            width: 2rem;
        }

        .panoWrap {
            position: absolute;
            overflow: hidden;

        }

        .panoWrap>canvas {
            cursor: -webkit-grab;
            cursor: grab;
        }

        .panoControls.bottom {
            position: absolute;
            display: flex;
            justify-content: flex-end;
            /* width: 100%; */
            align-items: center;
            top: -0.6rem;
            padding: 0 0.2rem;
            right: 0px;
        }

        .panoControls>button,
        .panoControls>div,
        .panoControls>a,
        .panoControls>input {
            pointer-events: all;
        }

        button.holaGreen,
        .buttonLike.holaGreen {
            background: #1c1c1c;
            /* border: #62d128 solid 2px; */
            border: 0;
            color: #62d128;
        }

        .panoControls.bottom button,
        .panoControls.bottom .buttonLike {
            padding: 0.1rem 0.2rem;
            display: block;
            margin: 0 10px
        }



        .panoControls.bottom [data-todo="share"] {
            position: relative;
        }

        .panoControls.bottom [data-todo="share"] ul {
            display: none;
            position: absolute;
            bottom: 0.36rem;
            left: 0;
        }

        .panoControls.bottom [data-todo="share"]:hover ul {
            display: block;
        }

        .panoControls.bottom [data-todo="share"] ul>li {
            padding: 0.75em 0.4em;
            text-align: center;
        }

        .panoControls.bottom [data-todo="share"] ul>li:hover {
            background-color: #62d128;
            color: #fff
        }

        .panoControls.onscreen {
            position: absolute;
            width: 100%
        }

        .panoControls.onscreen button {
            padding: 0.1rem 0.2rem;
            display: block;
            margin: 0 auto;
        }

        .panoPanelBottom button.rollOutBtn {
            position: absolute;
            height: 2em;
            top: -2em;
        }

        .panoPanelBottom {
            position: absolute;
            width: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            bottom: 0;
            transition: 0.4s ease bottom;
            padding-top: 0.1rem;
        }

        .panoPanelBottom.fold {
            bottom: -1.6rem;
        }


        .panoList {
            position: relative;
        }

        .panoList>ul {
            display: flex;
            color: #fff;
            margin: 0 auto;
            margin-bottom: 0.5em;
            user-select: none;
        }

        .panoList>ul li {
            display: flex;
            flex-direction: column;
            color: #fff;
            justify-content: center;
            margin: 0 10px;
            align-items: center;
        }

        .panoList>ul li>img.panoThumb {
            width: 1.5rem;
            display: block;
            min-width: 1.5rem;
            flex-shrink: 0;
        }

        .panoList>ul li>p.panoTitle {
            line-height: 1.5em;
            text-align: center;
            flex-shrink: 0;
            display: block;
            word-break: keep-all;
            overflow: hidden;
            text-overflow: ellipsis;
        }

        .panoNearbyWrap {
            width: 3rem;
            background-color: rgba(0, 0, 0, 0.5);
            position: absolute;
            right: 0.16rem;
            top: 0.16rem;
            height: max-content;
            color: #fff;
            resize: vertical;
        }

        .panoNearbyWrap>h2 {
            line-height: 0.6rem;
            text-align: center;
            font-size: 0.16rem;
            font-weight: 400;
            /* border-bottom: 1px solid rgba(255, 255, 255, 1); */
            display: flex;
            align-items: center;
            padding: 0 0.2rem;
            justify-content: space-between;
        }

        .panoNearbyWrap>h2 input {
            border: 0;
            background: rgba(0, 0, 0, 0);
            text-align: inherit;
            font: inherit;
            color: #fff;
            width: 2.4rem;
        }

        .panoNearbyWrap>h2 button {
            width: 0.3rem;
            height: 0.3rem;
        }

        .panoNearbyWrap>ul {
            overflow-y: auto;
            overflow-x: hidden;
            height: 4rem;
            font-size: 0.14rem;
            transition: 0.5s ease height;
        }

        .panoNearbyWrap>ul::-webkit-scrollbar {
            width: 0.08rem;
            border-radius: 0.04rem 0.04rem 0.04rem 0.04rem
        }

        .panoNearbyWrap>ul::-webkit-scrollbar-thumb {
            background-color: #62d128;
            border-radius: 0.04rem 0.04rem 0.04rem 0.04rem
        }

        .panoNearbyWrap>ul.fold {
            height: 0;
        }

        .panoNearbyWrap>ul>li>a {
            display: flex;
            justify-content: space-between;
            padding: 0.1rem 0.05rem;
            transition: ease 0.2s background-color;
            cursor: pointer;
            color: #fff
        }

        .panoNearbyWrap>ul>li:hover {
            background-color: #62d128;
        }

        .panoNearbyWrap>ul>li .title {
            margin-left: 1em;
        }

        .panoNearbyWrap>ul>li .distance {
            width: 4em;
            text-align: right;
            margin-left: 1em;
            flex-shrink: 0;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="logo">
            <img src="../logo.svg" />
        </div>
        <div class="panoWrap">
            <div class="panoControls onscreen">
                <button data-role="btn" data-todo="exitVR" class="holaGreen" v-if="ui.VRStatus">退出VR</button>
            </div>
        </div>
        <div class="panoPanelBottom" v-cloak :class="{'fold':ui.panoPanelBottomFold}">
            <button v-on:click="panoListRollToggle" class="rollOutBtn holaGreen">展开收起</button>

            <div class="panoList" data-role="panoList">
                <ul>
                    <li v-for="(pano,index) in panosList">
                        <img class="panoThumb" lazyload="on" @click="panoLoad(index)"
                            :src="panoThumbPath+pano.imgThumb" />
                        <p class="panoTitle">{{pano.desc}}</p>
                    </li>
                </ul>
                <!-- 滚动条 -->

            </div>

            <div class="panoControls bottom">
                <!-- <div data-role="btn" data-todo="share" class="holaGreen buttonLike shareButtonList">
                    <span>分享</span>
                    <ul data-role="shareWidget">
                        <li data-sns="weibo">微博</li>
                        <li data-sns="qz">QQ空间</li>
                        <li data-sns="linkedin">Linkedin</li>
                        <li data-sns="fb">Facebook</li>
                        <li data-sns="twitter">Twitter</li>
                    </ul>
                </div> -->
                <button data-role="btn" data-todo="shot" class="holaGreen">截屏</button>
                <button data-role="btn" data-todo="enterVR" class="holaGreen">VR</button>
                <button data-role="btn" data-todo="toggleFullScreen" class="holaGreen">全屏</button>
                <button data-role="btn" data-todo="toggleOrient" class="holaGreen">陀螺仪</button>
                <button data-role="btn" data-todo="togglePointer" class="holaGreen">鼠标</button>
            </div>
        </div>
        <div class="panoNearbyWrap">
            <h2 v-on:click="foldNeighbor()">
                查找附近
                <!-- <input name="findNearby" v-model="neighborSearchKeyword" placeholder="查找附近" />
                <button class="holaGreen" v-on:click="manualSearch()" >→</button> -->
                <button class="holaGreen">×</button>
            </h2>
            <ul class="nearbyList" v-cloak :class="{'fold':ui.neighborFold}">
                <li class="nearbyItems" v-for="(nearby,index) in poiObjArr">
                    <a :href="nearby.detailUrl" target="_blank">
                        <div class="title">{{nearby.posName}}</div>
                        <div class="distance">{{nearby.posDistance}}</div>
                    </a>
                </li>
            </ul>
        </div>
    </div>

    <!-- <script src="./pano_array.js"></script> -->
    <!-- <script src="./position2_array.js"></script> -->
    <script src="./js/slidebar.js"></script>

    <script>
        'use strict';
        var panoApp = new Vue({
            el: '#app',
            data: {
                //附近查询关键字
                neighborSearchKeyword: '',
                neighborSearchResult: [],
                //UI状态
                ui: {
                    panoPanelBottomFold: false,
                    neighborFold: true,
                    VRStatus: false
                },
                //检测是否存在用户交互
                userInteract: false,
                //标识是否暂停旋转动画
                pauseRotete: false,
                //配置全景图文件夹基地址
                panoBasePath: "./pano_images/",
                panoThumbPath: "./pano_thumb/",
                //存储全景图列表，未来通过Ajax来获得。
                //全景图列表中保存的经纬度：若来自用户的相机，在使用时应当首先接入百度地图来进行位置修正，返回百度地图中的坐标
                panosList: null,
                // panosList: panos,
                //存储百度地图地点列表，未来通过访问百度地图API来获得
                neighborList: [],//尝试把neighborList加到panosList的作为子对象

                // neighborList: positions,
                //当前全景图索引，未来试图通过Ajax来获得首次载入时的索引
                currentIndex: 0,
                //当前的鼠标坐标
                pointData: {
                    originX: 0,
                    originY: 0,
                    offsetX: 0,
                    offsetY: 0,
                    originTheta: 0,
                    originPhi: 0
                },
                //存储Poi对象的数组
                poiObjArr: []
            },
            computed: {
                _neighborSearchResult: {
                    set: function (val) {
                        console.log(val);
                        this.addPoi(val);
                    },
                    get: function () {
                        return this.neighborSearchResult;
                    }
                }
            },
            beforeCreate: function () {
                //在vue实例创建之前，获得全景列表
                var _this = this;
                var xhr = new XMLHttpRequest();
                xhr.open('GET', './pano_array.json');
                xhr.send();
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4 && xhr.status === 200) {
                        _this.panosList = JSON.parse(xhr.responseText);
                        console.log(_this.panosList);
                    }
                };
            },
            beforeMount: function () {

            },
            mounted: function () {
                var _this = this;
                //将事件中的this进行bind
                _this.eventHandlerBind();
                //初始化场景
                _this.sceneInit();
                //加入鼠标事件
                _this.attachController('mouse');
                // _this.attachController('orient');

                //为页面中各个按钮增加事件
                _this.btnTodoHandler();



                //初始化sprite
                _this.spriteGroupInit();


                var times = 0;
                var a = setInterval(function () {
                    if (_this.panosList === null) {
                        times++;
                        if (times >= 200) {
                            clearInterval(a)
                            console.log('未获得全景列表');
                        }
                        return;
                    } else {
                        _this.panoListTodo()
                        //传入全景图索引值，来确定应当以哪一张全景图来开场
                        _this.panoInit(_this.currentIndex);
                        _this.loadMap();
                        clearInterval(a);
                    }
                }, 20)

            },

            methods: {


                //基本场景初始化
                sceneInit: function () {

                    // window.a = new SlideBar(50, 100,document.querySelector('[data-role="panoList"]'));

                    var scene = new THREE.Scene();
                    //用于将scene暴露到全局，仅在调试时使用
                    window.scene = scene;
                    //默认相机为位于原点的透视相机
                    //fov,aspect,near,far
                    var defaultCamera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 1000);
                    defaultCamera.name = "defaultCamera";

                    var cameraGroup = new THREE.Group();
                    cameraGroup.name = "cameraGroup"
                    cameraGroup.add(defaultCamera);
                    scene.add(cameraGroup);

                    var renderer = new THREE.WebGLRenderer({
                        "antialias": true
                    });

                    //加光
                    var light = new THREE.AmbientLight(0xffffff, 2);
                    scene.add(light);

                    //尝试将设置设备像素比，防止手机浏览器渲染时产生锯齿。
                    renderer.setSize(window.innerWidth, window.innerHeight);
                    renderer.setPixelRatio(window.devicePixelRatio);

                    //将渲染器 - Canvas元素插入到DOM中
                    var panoWrap = document.getElementById('app').querySelector('.panoWrap');
                    panoWrap.appendChild(renderer.domElement);

                    //摄像机目标
                    var cameraTarget = new THREE.Object3D();
                    cameraTarget.name = "cameraTarget";
                    //第一个值为半径，第二个值为上下旋转角，第三个值为平面极坐标的旋转角
                    var panoSphereRadius = 10;
                    var targetSphereCood = new THREE.Spherical(panoSphereRadius, util.degToRad(225), 0);
                    cameraTarget.position.setFromSpherical(targetSphereCood);

                    scene.add(cameraTarget);

                    //添加窗口缩放事件
                    window.addEventListener('resize', this.resizeHandler.bind(this), false);

                    this.scene = scene;
                    this.camera = defaultCamera;
                    this.defaultCamera = defaultCamera;
                    this.cameraGroup = cameraGroup;
                    this.renderer = renderer;
                    this.panoWrap = panoWrap;
                    this.light = light;
                    this.cameraTarget = cameraTarget;
                    this.targetSphereCood = targetSphereCood;
                    this.panoSphereRadius = panoSphereRadius;

                    console.log(this.targetSphereCood);


                },
                //全景球初始化
                panoInit: function (panoIndex) {
                    //全景球半径为10
                    var panoGeometry = new THREE.SphereBufferGeometry(this.panoSphereRadius, 36, 36);
                    //直接将x设为-1，使得所有面朝向内测
                    panoGeometry.scale(-1, 1, 1);


                    //载入贴图
                    this.panoLoad(panoIndex);

                    var panoPhotoMaterial = new THREE.MeshStandardMaterial({
                        "map": this.panoImgTex,
                        "color": 0xffffff,
                    });
                    var panoSphere = new THREE.Mesh(panoGeometry, panoPhotoMaterial);
                    this.scene.add(panoSphere);

                    this.panoGeometry = panoGeometry;
                    // this.panoImgTex = panoImgTex;
                    this.panoPhotoMaterial = panoPhotoMaterial;
                    this.panoSphere = panoSphere;

                    console.log(this.camera);


                    this.renderer.render(this.scene, this.camera);

                    this.animateHandler();

                    //阻止默认的鼠标右键菜单弹出
                    this.panoWrap.addEventListener('contextmenu', function (e) {
                        e.preventDefault();
                    }, false);
                },

                panoListTodo: function () {
                    //全景列表处理
                    var panoListDOM = document.querySelector('[data-role="panoList"]>ul');
                    console.log(panoListDOM.scrollWidth - window.innerWidth);
                    window.a = new SlideBar(0, panoListDOM.scrollWidth - window.innerWidth, document.querySelector('[data-role="panoList"]'), function (val) {
                        console.log()
                        console.log(val);
                        panoListDOM.style.marginLeft = -val.value + 'px';
                    });
                    window.addEventListener('resize', function (e) {
                        a.max = panoListDOM.scrollWidth - window.innerWidth;
                    }, false)
                },

                //根据对应的panosList索引来载入对应全景照片。
                panoLoad: function (index) {

                    var _this = this;

                    this.panoImgTex = new THREE.TextureLoader().load(this.panoBasePath + this.panosList[index].imgName,
                        function (e) {
                            _this.panoImgTex.anisotropy = 8;

                            e.image.src = _this.panoBasePath + _this.panosList[index].imgName;
                            if (index == _this.currentIndex) {
                                return;
                            } else {
                                _this.currentIndex = index;
                                _this.panoImgTex.dispose();

                                _this.panoPhotoMaterial.map = e;

                                // _this.panoImgTex.needsUpdate = true;

                                for (let i = 0; i < _this.spriteGroup.length; i++) {
                                    _this.spriteGroup[i].dispose();//在切换之前把当前全景上所有的sprite poi清空
                                }
                                _this.spriteGroup.children = [];//在切换之前把当前全景上所有的sprite poi清空

                                // for (let i = 0; i < _this.poiObjArr.length; i++) {
                                //     _this.poiObjArr[i].dispose();
                                //     _this.poiObjArr[i].material.dispose();
                                //     _this.poiObjArr[i].material.map.needsUpdate = false;
                                //     _this.poiObjArr[i].material.map.dispose();
                                // }

                                //切换之后，读取相关数据，重新将sprite加入场景
                                // _this.panoImgTex.needsUpdate = false;

                                _this.loadMap();

                            }
                        });

                },

                //与事件相关的各种UI逻辑
                eventHandlerBind: function () {
                    this.eventBind = {};
                    //事件处理函数中this指向的是addEventListener的元素，因此需要bind
                    //但使用bind会生成一个新的函数，没法removeEventListener，在此先将函数预先bind
                    this.eventBind.deviceOrientationHandler = this.deviceOrientationHandler.bind(this);
                    this.eventBind.orientationChangeHandler = this.orientationChangeHandler.bind(this);
                    this.eventBind.pointHandler = this.pointHandler.bind(this);
                    this.eventBind.pointRayHandler = this.pointRayHandler.bind(this);
                    this.eventBind.mouseScrollHandler = this.mouseScrollHandler.bind(this);
                },
                //全景交互
                attachController: function (eventOption) {

                    //处理一下某些事件的兼容性问题
                    /*
                    FireFox中鼠标滚轮事件为DOMMouseScroll
                    */

                    switch (eventOption) {
                        //陀螺仪和鼠标之间暂时没想到并存的办法。
                        //正常方案：在陀螺仪开启的情况下，可能使用触摸来更改cameraTarget的方向
                        case 'mouse':
                        case 'touch': {
                            this.pauseRotete = false;
                            window.removeEventListener("deviceorientation", this.eventBind.deviceOrientationHandler, false);
                            window.removeEventListener('orientationchange', this.eventBind.orientationChangeHandler, false);
                            this.panoWrap.addEventListener("mousedown", this.eventBind.pointHandler, false);
                            this.panoWrap.addEventListener('touchstart', this.eventBind.pointHandler, false);
                            this.panoWrap.addEventListener("mousedown", this.eventBind.pointRayHandler, false);
                            this.panoWrap.addEventListener("mousewheel", this.eventBind.mouseScrollHandler, false);
                            break;
                        };
                        case 'orient': {
                            this.panoWrap.removeEventListener("mousedown", this.eventBind.pointHandler, false);
                            this.panoWrap.removeEventListener('touchstart', this.eventBind.pointHandler, false);
                            this.panoWrap.removeEventListener("mousedown", this.eventBind.pointRayHandler, false);
                            this.panoWrap.removeEventListener("mousewheel", this.eventBind.mouseScrollHandler, false);
                            window.addEventListener("deviceorientation", this.eventBind.deviceOrientationHandler, false);
                            window.addEventListener('orientationchange', this.eventBind.orientationChangeHandler, false);
                            break;
                        };
                    }
                },
                //DOM控件交互
                //伸展下方栏
                panoListRollToggle: function () {
                    !this.ui.panoPanelBottomFold ? this.ui.panoPanelBottomFold = true : this.ui.panoPanelBottomFold = false
                },
                //画面控制按钮
                btnTodoHandler: function () {
                    var _this = this;
                    var controlerGroups = document.querySelectorAll('.panoControls');
                    controlerGroups.forEach(group => {
                        group.addEventListener('click', function (e) {
                            switch (e.target.dataset.todo) {
                                case 'toggleFullScreen': {
                                    fullScreen(document.querySelector('body'), false);
                                    break;
                                };
                                case 'enterVR': {
                                    _this.enterVR();
                                    break;
                                };
                                case 'exitVR': {
                                    _this.exitVR();
                                    break;
                                };
                                case 'toggleOrient': {
                                    _this.attachController('orient');
                                    break;
                                };
                                case 'togglePointer': {
                                    _this.attachController('mouse')
                                    break;
                                }
                                case 'shot': {
                                    _this.shot(document.querySelector('.panoWrap').getElementsByTagName('canvas')[0]);
                                    break;
                                }
                            }
                        }, false)
                    });
                },

                //动画处理
                //全景球旋转动画    //setInterval(animate,100);
                panoRotationAnimate: function () {
                    //交互部分
                    //判断是否存在用户交互
                    //无交互、且无暂停
                    if (!this.userInteract) {
                        if (!this.pauseRotete) {
                            this.targetSphereCood.theta += util.degToRad(0.075);
                            this.cameraTarget.position.setFromSpherical(this.targetSphereCood);
                            //判断当前相机是否为相机阵列，如果是的话在请求动画时需要遍历更新子相机
                            if (this.camera instanceof THREE.ArrayCamera === false) {
                                this.camera.lookAt(this.cameraTarget.position);
                                //console.log(this.cameraTarget.position);
                            } else {
                                for (var i = 0; i < this.camera.cameras.length; i++) {
                                    this.camera.cameras[i].lookAt(this.cameraTarget.position);
                                }
                            }
                        }
                    }
                },

                //sprite渲染动画
                spriteInitRender: function () {
                    for (var i = 0; i < this.poiObjArr.length; i++) {
                        // this.poiObjArr[i].poiObject.material.needsUpdate = true;
                        if (this.poiObjArr[i].poiObject.material.map.version < 5) {
                            this.poiObjArr[i].poiObject.material.map.needsUpdate = true
                        };
                    }
                },

                //动画总控
                animateHandler: function () {
                    this.panoRotationAnimate();
                    this.spriteInitRender();
                    this.renderer.render(this.scene, this.camera);
                    // console.log(this.renderer)
                    //注意this指向，在定时器中this指向window
                    requestAnimationFrame(this.animateHandler.bind(this));
                },
                /*
                交互方式：
                改变全景照片的方向
                鼠标/触摸：在屏幕上上下滑动改变上下旋转角，左右滑动更改平面旋转角；
                设备朝向：移动设备改变摄像机目标的位置
                改变摄像机的FOV
                鼠标滚轮：向前放大，向后缩小
                */
                //处理鼠标或者触摸屏事件
                pointHandler: function (e) {
                    //鼠标拖动全景球事件由鼠标左键来触发
                    if (e.type.match('mouse') || e.type == 'click') {
                        if (e.button != 0) {
                            return;
                        }
                    }

                    var evtType = e.type;

                    // e.preventDefault();

                    if (e.type.match('touch')) {
                        e = e.touches[0];
                    }

                    //事件处理函数中this指向的是addEventListener的元素
                    // console.log(this);

                    switch (evtType) {
                        case "touchstart":
                        case "mousedown": {
                            this.renderer.domElement.style.cursor = 'grab';

                            this.userInteract = true;
                            //得到鼠标点击位置
                            this.pointData.originX = e.clientX;
                            this.pointData.originY = e.clientY;

                            //
                            this.pointData.originTheta = this.targetSphereCood.theta;
                            this.pointData.originPhi = this.targetSphereCood.phi;
                            //

                            this.panoWrap.addEventListener("mousemove", this.eventBind.pointHandler, false);
                            this.panoWrap.addEventListener("mouseup", this.eventBind.pointHandler, false);

                            this.panoWrap.addEventListener("touchmove", this.eventBind.pointHandler, false);
                            this.panoWrap.addEventListener("touchend", this.eventBind.pointHandler, false);

                            break;
                        }
                        case "touchmove":
                        case "mousemove": {
                            this.renderer.domElement.style.cursor = 'grabbing';

                            if (this.userInteract) {

                                //鼠标移动时计算鼠标的偏移量
                                this.pointData.offsetX = e.clientX - this.pointData.originX;
                                this.pointData.offsetY = e.clientY - this.pointData.originY;

                                //
                                this.targetSphereCood.theta = this.pointData.offsetX * 0.005 + this.pointData.originTheta;
                                // console.log(util.radToDeg(sphereCood.phi))

                                var phi = this.pointData.offsetY * 0.005 + this.pointData.originPhi;
                                //限制上下俯仰角度，以防万向锁。来自THREEJS
                                this.targetSphereCood.phi = util.clamp(phi, util.degToRad(181), util.degToRad(359));

                                // console.log(sphereCood.theta + ' ' + sphereCood.phi)

                                this.cameraTarget.position.setFromSpherical(this.targetSphereCood);
                                this.camera.lookAt(this.cameraTarget.position);

                            }
                            break;
                        }

                        case "touchend":
                        case "mouseup": {
                            this.renderer.domElement.style.cursor = 'grab';
                            this.userInteract = false;

                            this.panoWrap.removeEventListener("mouseup", this.eventBind.pointHandler, false);
                            this.panoWrap.removeEventListener("touchend", this.eventBind.pointHandler, false);

                            this.panoWrap.removeEventListener("mousemove", this.eventBind.pointHandler, false);
                            this.panoWrap.removeEventListener("touchmove", this.eventBind.pointHandler, false);


                            break;
                        }
                    }
                },
                //处理窗口大小改变时三维场景的变化
                resizeHandler: function (e) {
                    this.renderer.setSize(window.innerWidth, window.innerHeight);
                    this.camera.aspect = window.innerWidth / window.innerHeight;
                    this.camera.updateProjectionMatrix();
                },

                //处理光线投射
                pointRayHandler: function (e) {
                    if (e.type.match('mouse') || e.type == 'click') {
                        //如果按下的按键为鼠标左键则不进行光线投射
                        if (e.button == 0) {
                            return;
                        }
                    }
                    var mouse = new THREE.Vector2();
                    // console.log(event);
                    var raycaster = new THREE.Raycaster();
                    e.preventDefault();
                    //将浏览器坐标转换到Threejs坐标
                    mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
                    mouse.y = - (e.clientY / window.innerHeight) * 2 + 1;

                    raycaster.setFromCamera(mouse, this.camera);
                    console.log(this.camera);

                    //一个数组，用于保存与射线相交叉的对象
                    //数组下标按照物体远近来进行排序，下标越大越远
                    var intersects = raycaster.intersectObjects(scene.children)
                    //尝试把射线选中的除了全景球以外的元素删去
                    //似乎可以用.filter(function(obj3d){return ...});来替换？
                    var realIntersects = [];
                    for (var i = 0; i < intersects.length; i++) {
                        // console.log(intersects);
                        if (intersects[i].object.geometry instanceof THREE.SphereBufferGeometry) {
                            realIntersects.push(intersects[i]);
                        }
                    }
                    // console.log(realIntersects);
                    var intersectPoint = realIntersects[0].point;
                    console.log(intersectPoint);
                },
                //处理鼠标滚轮
                mouseScrollHandler: function (e) {
                    // console.log(e)
                    //主要是更改场景中相机的fov以及相机y坐标
                    // console.log(e);
                    // console.log(this.camera.fov);
                    // console.log(this.cameraGroup.position.y);

                    //相机在y轴上位置范围：0~4.5，fov范围：75~120

                    // if (this.camera.fov <= 120 && this.camera.position.y<=4.5) {
                    this.camera.fov += 0.006 * e.deltaY;
                    this.cameraGroup.position.y += 0.001 * e.deltaY;

                    this.camera.fov = util.clamp(this.camera.fov, 75, 120);
                    this.cameraGroup.position.y = util.clamp(this.cameraGroup.position.y, 0, 4.5);

                    this.camera.updateProjectionMatrix();
                    // }

                },
                //处理设备方向
                orientationChangeHandler: function (e) {
                    //console.log(e);
                },
                deviceOrientationHandler: function (e) {
                    this.pauseRotete = true;
                    //这个值表示屏幕朝向，当屏幕朝向变的时候改变这个值
                    //+-------+   +---------------+   +---------------+
                    //|       |   |               |   |               |
                    //|       |   |      +90    < |   | >     -90     |
                    //|   0   |   |               |   |               |
                    //|       |   +---------------+   +---------------+
                    //|   ^   |                                  
                    //+-------+                                  
                    var screenOrientation = window.orientation || 0;//桌面端似乎不存在window.orientation
                    //代码来自threejs  //
                    var euler = new THREE.Euler();
                    if (screenOrientation == 0) {
                        euler.set(util.degToRad(e.beta), util.degToRad(e.alpha), util.degToRad(-e.gamma), 'YXZ');//从传感器新建一个欧拉角
                    }

                    if (screenOrientation == 90) {
                        euler.set(util.degToRad(e.beta), util.degToRad(e.alpha), util.degToRad(-e.gamma + 45), 'YXZ');//从传感器新建一个欧拉角
                    }

                    var q0 = new THREE.Quaternion();
                    var q1 = new THREE.Quaternion(- Math.sqrt(0.5), 0, 0, Math.sqrt(0.5)); // - PI/2 around the x-axis
                    var qn = new THREE.Quaternion().setFromEuler(euler);
                    qn.multiply(q1);
                    qn.multiply(q0.setFromAxisAngle(new THREE.Vector3(0, 0, 1), -screenOrientation));

                    this.camera.setRotationFromQuaternion(qn)
                    // this.cameraTarget.quaternion=qn;
                    console.log(this.camera.quaternion)
                },

                //场景中Sprite组初始化
                spriteGroupInit: function () {
                    var spriteOutterGroup = new THREE.Group();
                    spriteOutterGroup.name = "spriteOutterGroup";
                    var spriteGroup = new THREE.Group();
                    spriteGroup.name = "spriteGroup";
                    spriteGroup.scale.x = -1;
                    spriteGroup.scale.y = -1;
                    spriteGroup.rotation.y = util.degToRad(-90);
                    spriteOutterGroup.add(spriteGroup);
                    scene.add(spriteOutterGroup);

                    this.spriteGroup = spriteGroup;
                },

                //切换到VR
                enterVR: function () {
                    this.ui.VRStatus = true;


                    var element = document.querySelector('.panoWrap');
                    if (document.fullscreenElement) {
                        fullScreen('exit');
                        fullScreen(element, true);
                    } else {
                        fullScreen(element, true);
                    }
                    // element.addEventListener('fullscreenchange', function (e) {
                    //     console.log(e);
                    //     fullScreen('exit');
                    // });
                    this.attachController('orient');

                    if (!this.hmdGlasses) {
                        //设置左眼右眼
                        var rightCamera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight / 2, 0.1, 1000);
                        rightCamera.name = "rightCamera";
                        var leftCamera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight / 2, 0.1, 1000);
                        leftCamera.name = "leftCamera";

                        //设置相机的边界
                        leftCamera.bounds = new THREE.Vector4(0, 0, 0.5, 1);
                        rightCamera.bounds = new THREE.Vector4(0.5, 0, 0.5, 1);

                        //瞳距
                        leftCamera.position.x = -0.2;
                        rightCamera.position.x = 0.2;

                        // leftCamera.lookAt(this.cameraTarget);
                        // rightCamera.lookAt(this.cameraTarget);

                        var hmdGlasses = new THREE.ArrayCamera([leftCamera, rightCamera]);

                        hmdGlasses.name = "hmdGlasses";

                        // hmdGlasses.lookAt(this.cameraTarget);

                        hmdGlasses.add(leftCamera);
                        hmdGlasses.add(rightCamera);
                        this.cameraGroup.add(hmdGlasses);

                        this.hmdGlasses = hmdGlasses;
                    }

                    this.camera = this.hmdGlasses;

                },

                //退出VR
                exitVR: function () {
                    var _this = this;
                    fullScreen('exit', false, function () {
                        if (document.fullscreenElement === null) {
                            _this.ui.VRStatus = false;
                            _this.attachController('mouse');
                            _this.camera = _this.defaultCamera;
                        }
                    })
                },

                //计算poi与全景拍摄距离，并将得到的距离赋值给源对象
                poiCalc: function (coodA, coodB) {
                    var poiInfo = {
                        distance: util.geoLength(coodA, coodB),
                        angle: util.geoAngle(coodA, coodB)
                    };
                    return poiInfo;
                },

                //加载地图函数
                loadMap: function () {

                    var times = 0, _this = this;
                    var a = setInterval(function () {
                        if (_this.panosList.length == 0) {
                            if (times < 30) {
                                console.log('全景列表加载失败');
                                times++;
                                return;
                            }
                        } else {
                            console.log(_this.panosList)
                            clearInterval(a);

                            //搜索poi
                            if (_this.neighborList[_this.currentIndex] === undefined) {
                                _this.neighborList[_this.currentIndex] = [];
                            }

                            //防止重复加载 //若当前neighborList对应的当前数组中已经有了元素，就直接加入到场景中，不必再去请求
                            if ((_this.neighborList[_this.currentIndex] instanceof Array) && (_this.neighborList[_this.currentIndex].length > 0)) {
                                _this.addPoi(_this.neighborList[_this.currentIndex]);
                                return;
                            } else {
                                new BaiduMap(_this.panosList[_this.currentIndex].geoCood.lng, _this.panosList[_this.currentIndex].geoCood.lat, '美食', 2000, _this.neighborList[_this.currentIndex]);
                            }


                            //将Poi板添加到三维场景中
                            //异步问题：poi板上会在其中的icon（img）被加载前就被添加到三维场景，此时添加到三维场景中的poi板上不会显示icon；//解决方式：将poiboard材质下map的needsUpdate设为true
                            var times = 0;
                            a = setInterval(function () {
                                console.log(_this.neighborList[_this.currentIndex]);

                                if (_this.neighborList[_this.currentIndex].length === 0) {
                                    if (times < 30) {
                                        _this.ui.neighborFold = true;
                                        console.log('正在加载附近数据');
                                        times++;
                                        return;
                                    } else {
                                        console.log('加载超时');
                                        _this.ui.neighborFold = true;

                                        clearInterval(a);
                                    }
                                } else {
                                    console.log('加载成功');
                                    _this.ui.neighborFold = false;
                                    clearInterval(a);
                                    _this.addPoi(_this.neighborList[_this.currentIndex]);
                                }
                            }, 200)
                        }
                    }, 100)
                },

                //将poiBoard加入到场景中
                addPoi: function (bMapArray) {
                    console.log(bMapArray)
                    console.log(bMapArray.length)
                    // if (bMapArray.length!==undefined) {
                    //     for (let i = 0; i < bMapArray.length; i++) {
                    //         console.log(bMapArray[i])

                    //         // bMapArray[i].dispose();
                    //         // bMapArray.remove(bMapArray[i]);
                    //     }
                    // }

                    var originP = this.panosList[this.currentIndex].geoCood;
                    this.poiObjArr = [];
                    for (var i = 0; i < bMapArray.length; i++) {
                        bMapArray[i].poiInfo = this.poiCalc(originP, bMapArray[i].point);//算出poi与全景照片拍摄点的距离和角度
                        // console.log(bMapArray[i].poiInfo);
                        var distanceText;
                        if (bMapArray[i].poiInfo.distance > 1000) {
                            distanceText = (bMapArray[i].poiInfo.distance / 1000).toFixed(1) + ' km';
                        } else {
                            distanceText = bMapArray[i].poiInfo.distance.toFixed(0) + ' m';
                        }

                        //生成sprite
                        var poiObj = new PoiBoard(bMapArray[i].title, distanceText, bMapArray[i].detailUrl);
                        // console.log(poiObj);
                        poiObj.poiObject.material.needsUpdate = true;
                        poiObj.poiObject.material.map.needsUpdate = true;
                        this.poiObjArr.push(poiObj);

                        // console.log(this.poiObjArr)

                        // //有了角度、有了距离，算球坐标
                        // //俯仰角根据poi距离来确定，角度值在90~180之间
                        // console.log(bMapArray[i].poiInfo.distance / 2000 * 180);
                        // var lengthVal = util.clamp(bMapArray[i].poiInfo.distance / 2000 * this.panoSphereRadius, 0.2 * this.panoSphereRadius, this.panoSphereRadius * 0.3);//poi半径长度，poi越远值越大，但限制在给定范围内
                        // var pitchVal = util.degToRad(util.clamp(bMapArray[i].poiInfo.distance / 2000 * 180 + util.rand(-20, 20), 75, 90));//poi球坐标的俯仰角，角度值在90~180之间。
                        // var azimuthVal = util.degToRad(bMapArray[i].poiInfo.angle);//poi球坐标的方位角

                        // // console.log(lengthVal)
                        // var poiSpherical = new THREE.Spherical(lengthVal, pitchVal, azimuthVal);

                        // var poiCood = new THREE.Vector3().setFromSpherical(poiSpherical);
                        // // console.log(poiCood);
                        // poiObj.poiObject.position.x = poiCood.x;
                        // poiObj.poiObject.position.y = poiCood.y;
                        // poiObj.poiObject.position.z = poiCood.z;

                        // this.spriteGroup.add(poiObj.poiObject);

                    }
                },

                //全景截图，相当于Canvas截取图片
                shot: function (canvas) {
                    //如果没有传入canvas元素或者传入的不是canvas元素，就默认将canvas参数设为获得的第一个canvas元素
                    if (!(canvas instanceof HTMLCanvasElement)) {
                        if (document.getElementsByTagName('canvas').length !== 0) {
                            canvas = document.getElementsByTagName('canvas')[0];
                        } else {
                            return;
                        }
                    }

                    //现渲染现截图，若不渲染就截图，会导致截到全黑画面
                    this.renderer.render(this.scene, this.camera);
                    // console.log(this.renderer.domElement.toDataURL('image/jpeg', 0.92));
                    // window.open();

                    var date = new Date();
                    var filenameTime = 'panoshot_' + date.getFullYear() + (date.getMonth() + 1) + date.getDate() + date.getHours() + date.getMinutes() + date.getSeconds();
                    var imglink = document.createElement('a');
                    imglink.download = filenameTime;
                    imglink.setAttribute('href', this.renderer.domElement.toDataURL('image/jpeg', 0.7));
                    console.log(imglink);
                    var event = new MouseEvent('click')
                    imglink.dispatchEvent(event);
                    // imglink.click()



                    // canvas.toBlob(
                    //     function (blob) {
                    //         console.log(blob)
                    //     },
                    //     'image/jpeg',
                    //     0.92
                    // );

                },
                foldNeighbor: function () {
                    this.ui.neighborFold ? this.ui.neighborFold = false : this.ui.neighborFold = true;
                },
                manualSearch: function () {
                    var _this = this;
                    _this.neighborSearchResult = [];
                    _this._neighborSearchResult = [];
                    _this.poiObjArr = [];
                    new BaiduMap(_this.panosList[_this.currentIndex].geoCood.lng, _this.panosList[_this.currentIndex].geoCood.lat, _this.neighborSearchKeyword, 2000, _this._neighborSearchResult);

                }
            }
        });


    </script>
    <a class="bshareDiv" href="http://www.bshare.cn/share">分享按钮</a>
    <script type="text/javascript" charset="utf-8"
        src="http://static.bshare.cn/b/buttonLite.js#uuid=&amp;style=3&amp;fs=4&amp;textcolor=#fff&amp;bgcolor=#9C3&amp;text=分享到"></script>
</body>

</html>